﻿using System.Collections.Generic;
using Cubicle.Core.Config;
using Cubicle.Core.DataContracts;
using Cubicle.Core.Interfaces;
using Cubicle.Core.Processors;
using ExcelDna.Integration;

namespace Cubicle.Excel.Hosting
{
    public abstract class EngineProxy
    {
        private readonly Processor<object> _marshalQueue;

        protected EngineProxy(string alias, Processor<object> marshalQueue)
        {
            Alias = alias;
            _marshalQueue = marshalQueue;
        }

        public string Alias { get; private set; }
        public abstract string Address { get; }
        public abstract bool IsConnected();
        public abstract string StartHost(HostingType type, bool enableMetaData, int port);
        public abstract bool StopHost();
        public abstract bool IsHosted { get; }
        public abstract string HostAddress { get; }

        public object Invoke(string handle, string memberName, object[,] parameters, object objKey = null,
                             object[] methodArgs = null, object[] classArgs = null)
        {
            //if (parameters != null && parameters[0, 0] is ExcelMissing) parameters = null;
            var result = ProxyInvoke(handle, memberName, parameters, objKey, methodArgs, classArgs);
            return _marshalQueue.Process(result);
        }

        public abstract object ProxyInvoke(string handle, string memberName, object[,] parameters, object objKey, object[] methodArgs = null, object[] classArgs = null);

        public abstract void Clear();
        public abstract string[] List();
        public abstract string Rename(string handle, string newKey);
        public abstract IRObject Remove(string handle);
        public abstract bool Has(string handle);
        public abstract string Set(string key, object item);

        public object Get(string handle)
        {
            return _marshalQueue.Process(GetProxy(handle));
        }

        public abstract object GetProxy(string handle);
        public abstract IRObject GetRObject(string handle);

        public abstract string Id { get; }
        public abstract object Process(Instruction instruction);
        public abstract bool Build(ProcessorConfig config);

        public abstract string GetVersion();
        public abstract IEnumerable<AssemblyData> GetAssemblyDetails();
        public abstract IEnumerable<MemberData> GetMembers(string target);
        public abstract IEnumerable<TypeData> GetTypes(string target);
        public abstract TypeData GetType(string target);
        public abstract IEnumerable<MethodData> GetMethods(string target);
        public abstract IEnumerable<FieldData> GetFields(string target);
        public abstract IEnumerable<PropertyData> GetProperties(string target);
        public abstract IEnumerable<ConstructorData> GetConstructors(string target);
        public abstract IEnumerable<ParameterData> GetParameterData(string target, string memberName, int offset);
        public abstract IEnumerable<string> GetLog(int i);
        public abstract bool RunScript(byte[] rawScript);

        public abstract string LoadAssembly(byte[] assembly, byte[] symbols = null);
    }
}